package com.wb.creational.builder;

import com.sun.org.apache.xpath.internal.operations.And;
import lombok.Data;
import lombok.ToString;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 魏彪
 */
public class BuilderTest01 {
    public static void main(String[] args) {
        // 通用写法
        IBuilder builder = new ConcreteBuilder();
        System.out.println(builder.build());

        // 实际应用
        CourseBuilder courseBuilder = new CourseBuilder();
        Course course = courseBuilder.addName("设计模式")
                .addPpt("PPT课件")
                .addVideo("录播视频")
                .builder();
        System.out.println(course);
    }
}

@Data
@ToString
class Product {
    private String name;
}

interface IBuilder {
    Product build();
}

class ConcreteBuilder implements IBuilder {

    private Product product = new Product();

    @Override
    public Product build() {
        return product;
    }
}

/**
 * 使用建造者模式解决实际问题
 */
@Data
@ToString
class Course {
    private String name;
    private String ppt;
    private String video;
    private String note;
    private String homework;
}

class CourseBuilder {
    private Course course = new Course();

    public CourseBuilder addName(String name) {
        course.setName(name);
        return this;
    }

    public CourseBuilder addPpt(String ppt) {
        course.setPpt(ppt);
        return this;
    }

    public CourseBuilder addVideo(String video) {
        course.setVideo(video);
        return this;
    }

    public CourseBuilder addNote(String note) {
        course.setNote(note);
        return this;
    }

    public CourseBuilder addHomework(String homework) {
        course.setHomework(homework);
        return this;
    }

    public Course builder() {
        return course;
    }
}

/**
 * 使用建造者模式动态构建SQL语句（JPA源码）
 */
final class QueryRule implements Serializable {
    public static final int ASC_ORDER = 101;
    public static final int DESC_ORDER = 102;
    public static final int LIke = 1;
    public static final int in = 2;
    public static final int NOTIN = 3;
    public static final int BETWEEN = 4;
    public static final int EQ = 5;
    public static final int NOT_EQ = 6;
    public static final int GT = 7;
    public static final int GE = 8;
    public static final int LT = 9;
    public static final int LE = 10;
    public static final int ISNULL = 11;
    public static final int IS_NOTNULL = 12;
    public static final int IS_EMPTY = 13;
    public static final int IS_NOT_EMPTY = 14;
    public static final int AND = 201;
    public static final int OR = 202;
    private List<Rule> ruleList = new ArrayList<>();
    private List<QueryRule> queryRuleList = new ArrayList<>();

    private String propertyName;

    private QueryRule() {
    }

    private QueryRule(String propertyName) {
        this.propertyName = propertyName;
    }

    public static QueryRule getInstance() {
        return new QueryRule();
    }

    public QueryRule addAscOrder(String propertyName) {
        this.ruleList.add(new Rule(ASC_ORDER, propertyName));
        return this;
    }

    public QueryRule addDescOrder(String propertyName) {
        this.ruleList.add(new Rule(DESC_ORDER, propertyName));
        return this;
    }

    public QueryRule addIsNull(String propertyName) {
        this.ruleList.add(new Rule(ISNULL, propertyName).setAndOr(AND));
        return this;
    }

    protected class Rule implements Serializable {
        // 规则类型
        private int type;
        private String property_name;
        private Object[] values;

        private int andOr = AND;

        public Rule(int paramType, String paramString) {
            this.type = paramType;
            this.property_name = paramString;
        }


        public Rule(int paramType, String paramString, Object[] paramArrayOfObject) {
            this.type = paramType;
            this.property_name = paramString;
            this.values = paramArrayOfObject;
        }

        public Rule setAndOr(int andOr) {
            this.andOr = andOr;
            return this;
        }

    }

}